{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Demand forecasting with BigQuery and TensorFlow\n",
    "\n",
    "In this notebook, we will develop a machine learning model to predict the demand for taxi cabs in New York.\n",
    "\n",
    "To develop the model, we will need to get historical data of taxicab usage. This data exists in BigQuery. Let's start by looking at the schema."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import google.datalab.bigquery as bq\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import shutil"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "    <div class=\"bqsv\" id=\"1_153685829288\"></div>\n",
       "    <script src=\"/static/components/requirejs/require.js\"></script>\n",
       "    <script>\n",
       "      require.config({\n",
       "        paths: {\n",
       "          base: '/static/base',\n",
       "        },\n",
       "        map: {\n",
       "          '*': {\n",
       "            datalab: 'nbextensions/gcpdatalab'\n",
       "          }\n",
       "        },\n",
       "      });\n",
       "\n",
       "      require(['datalab/bigquery', 'datalab/element!1_153685829288',\n",
       "          'datalab/style!/nbextensions/gcpdatalab/bigquery.css'],\n",
       "        function(bq, dom) {\n",
       "          bq.renderSchema(dom, [{\"type\": \"STRING\", \"name\": \"vendor_id\", \"description\": \"A code indicating the TPEP provider that provided the record. 1= Creative Mobile Technologies, LLC; 2= VeriFone Inc\", \"mode\": \"REQUIRED\"}, {\"type\": \"TIMESTAMP\", \"name\": \"pickup_datetime\", \"description\": \"The date and time when the meter was engaged.\", \"mode\": \"NULLABLE\"}, {\"type\": \"TIMESTAMP\", \"name\": \"dropoff_datetime\", \"description\": \"The date and time when the meter was disengaged.\", \"mode\": \"NULLABLE\"}, {\"type\": \"INTEGER\", \"name\": \"passenger_count\", \"description\": \"The number of passengers in the vehicle. This is a driver-entered value\", \"mode\": \"NULLABLE\"}, {\"type\": \"FLOAT\", \"name\": \"trip_distance\", \"description\": \"The elapsed trip distance in miles reported by the taximeter.\", \"mode\": \"NULLABLE\"}, {\"type\": \"FLOAT\", \"name\": \"pickup_longitude\", \"description\": \"Longitude where the meter was engaged.\", \"mode\": \"NULLABLE\"}, {\"type\": \"FLOAT\", \"name\": \"pickup_latitude\", \"description\": \"Latitude where the meter was engaged.\", \"mode\": \"NULLABLE\"}, {\"type\": \"INTEGER\", \"name\": \"rate_code\", \"description\": \"The final rate code in effect at the end of the trip. 1= Standard rate 2=JFK 3=Newark 4=Nassau or Westchester 5=Negotiated fare 6=Group ride\", \"mode\": \"NULLABLE\"}, {\"type\": \"STRING\", \"name\": \"store_and_fwd_flag\", \"description\": \"This flag indicates whether the trip record was held in vehicle memory before sending to the vendor, aka \\u201cstore and forward,\\u201d because the vehicle did not have a connection to the server. Y= store and forward trip N= not a store and forward trip\", \"mode\": \"NULLABLE\"}, {\"type\": \"FLOAT\", \"name\": \"dropoff_longitude\", \"description\": \"Longitude where the meter was disengaged\", \"mode\": \"NULLABLE\"}, {\"type\": \"FLOAT\", \"name\": \"dropoff_latitude\", \"description\": \"Latitude where the meter was disengaged.\", \"mode\": \"NULLABLE\"}, {\"type\": \"STRING\", \"name\": \"payment_type\", \"description\": \"A numeric code signifying how the passenger paid for the trip. 1= Credit card 2= Cash 3= No charge 4= Dispute 5= Unknown 6= Voided trip\", \"mode\": \"NULLABLE\"}, {\"type\": \"FLOAT\", \"name\": \"fare_amount\", \"description\": \"The time-and-distance fare calculated by the meter\", \"mode\": \"NULLABLE\"}, {\"type\": \"FLOAT\", \"name\": \"extra\", \"description\": \"Miscellaneous extras and surcharges. Currently, this only includes the $0.50 and $1 rush hour and overnight charges.\", \"mode\": \"NULLABLE\"}, {\"type\": \"FLOAT\", \"name\": \"mta_tax\", \"description\": \"$0.50 MTA tax that is automatically triggered based on the metered rate in use\", \"mode\": \"NULLABLE\"}, {\"type\": \"FLOAT\", \"name\": \"tip_amount\", \"description\": \"Tip amount \\u2013 This field is automatically populated for credit card tips. Cash tips are not included\", \"mode\": \"NULLABLE\"}, {\"type\": \"FLOAT\", \"name\": \"tolls_amount\", \"description\": \"Total amount of all tolls paid in trip.\", \"mode\": \"NULLABLE\"}, {\"type\": \"FLOAT\", \"name\": \"imp_surcharge\", \"description\": \"$0.30 improvement surcharge assessed trips at the flag drop. The improvement surcharge began being levied in 2015.\", \"mode\": \"NULLABLE\"}, {\"type\": \"FLOAT\", \"name\": \"total_amount\", \"description\": \"The total amount charged to passengers. Does not include cash tips\", \"mode\": \"NULLABLE\"}]);\n",
       "        }\n",
       "      );\n",
       "    </script>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%bq tables describe --name bigquery-public-data.new_york.tlc_yellow_trips_2015"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Analyzing taxicab demand\n",
    "\n",
    "Let's pull the number of trips for each day in the 2015 dataset using Standard SQL."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "    <div class=\"bqtv\" id=\"2_153685829604\"><table><tr><th>daynumber</th></tr><tr><td>301</td></tr><tr><td>178</td></tr><tr><td>308</td></tr><tr><td>336</td></tr><tr><td>150</td></tr></table></div>\n",
       "    <br />(rows: 5, time: 1.0s,     1GB processed, job: job_GP7k9U5JSFReoyXatKIhMU65sjWB)<br />\n",
       "    <script src=\"/static/components/requirejs/require.js\"></script>\n",
       "    <script>\n",
       "      require.config({\n",
       "        paths: {\n",
       "          base: '/static/base',\n",
       "          d3: '//cdnjs.cloudflare.com/ajax/libs/d3/3.4.13/d3',\n",
       "          plotly: 'https://cdn.plot.ly/plotly-1.5.1.min.js?noext',\n",
       "          jquery: '//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min'\n",
       "        },\n",
       "        map: {\n",
       "          '*': {\n",
       "            datalab: 'nbextensions/gcpdatalab'\n",
       "          }\n",
       "        },\n",
       "        shim: {\n",
       "          plotly: {\n",
       "            deps: ['d3', 'jquery'],\n",
       "            exports: 'plotly'\n",
       "          }\n",
       "        }\n",
       "      });\n",
       "\n",
       "      require(['datalab/charting', 'datalab/element!2_153685829604', 'base/js/events',\n",
       "          'datalab/style!/nbextensions/gcpdatalab/charting.css'],\n",
       "        function(charts, dom, events) {\n",
       "          charts.render('gcharts', dom, events, 'table', [], {\"cols\": [{\"type\": \"number\", \"id\": \"daynumber\", \"label\": \"daynumber\"}], \"rows\": [{\"c\": [{\"v\": 301}]}, {\"c\": [{\"v\": 178}]}, {\"c\": [{\"v\": 308}]}, {\"c\": [{\"v\": 336}]}, {\"c\": [{\"v\": 150}]}]},\n",
       "            {\n",
       "              pageSize: 25,\n",
       "              cssClassNames:  {\n",
       "                tableRow: 'gchart-table-row',\n",
       "                headerRow: 'gchart-table-headerrow',\n",
       "                oddTableRow: 'gchart-table-oddrow',\n",
       "                selectedTableRow: 'gchart-table-selectedrow',\n",
       "                hoverTableRow: 'gchart-table-hoverrow',\n",
       "                tableCell: 'gchart-table-cell',\n",
       "                headerCell: 'gchart-table-headercell',\n",
       "                rowNumberCell: 'gchart-table-rownumcell'\n",
       "              }\n",
       "            },\n",
       "            {source_index: 0, fields: 'daynumber'},\n",
       "            0,\n",
       "            5);\n",
       "        }\n",
       "      );\n",
       "    </script>\n",
       "  "
      ],
      "text/plain": [
       "QueryResultsTable job_GP7k9U5JSFReoyXatKIhMU65sjWB"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%bq query\n",
    "SELECT \n",
    "  EXTRACT (DAYOFYEAR from pickup_datetime) AS daynumber\n",
    "FROM `bigquery-public-data.new_york.tlc_yellow_trips_2015` \n",
    "LIMIT 5"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Modular queries and Pandas dataframe\n",
    "\n",
    "Let's use the total number of trips as our proxy for taxicab demand (other reasonable alternatives are total trip_distance or total fare_amount).  It is possible to predict multiple variables using Tensorflow, but for simplicity, we will stick to just predicting the number of trips.\n",
    "\n",
    "We will give our query a name 'taxiquery' and have it use an input variable '$YEAR'. We can then invoke the 'taxiquery' by giving it a YEAR.  The to_dataframe() converts the BigQuery result into a <a href='http://pandas.pydata.org/'>Pandas</a> dataframe."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "%bq query -n taxiquery\n",
    "WITH trips AS (\n",
    "  SELECT EXTRACT (DAYOFYEAR from pickup_datetime) AS daynumber \n",
    "  FROM `bigquery-public-data.new_york.tlc_yellow_trips_*`\n",
    "  where _TABLE_SUFFIX = @YEAR\n",
    ")\n",
    "SELECT daynumber, COUNT(1) AS numtrips FROM trips\n",
    "GROUP BY daynumber ORDER BY daynumber"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>daynumber</th>\n",
       "      <th>numtrips</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>382014</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2</td>\n",
       "      <td>345296</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3</td>\n",
       "      <td>406769</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4</td>\n",
       "      <td>328848</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5</td>\n",
       "      <td>363454</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   daynumber  numtrips\n",
       "0          1    382014\n",
       "1          2    345296\n",
       "2          3    406769\n",
       "3          4    328848\n",
       "4          5    363454"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "query_parameters = [\n",
    "  {\n",
    "    'name': 'YEAR',\n",
    "    'parameterType': {'type': 'STRING'},\n",
    "    'parameterValue': {'value': 2015}\n",
    "  }\n",
    "]\n",
    "trips = taxiquery.execute(query_params=query_parameters).result().to_dataframe()\n",
    "trips[:5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Benchmark\n",
    "\n",
    "Often, a reasonable estimate of something is its historical average. We can therefore benchmark our machine learning model against the historical average."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Just using average=400309.5589041096 has RMSE of 51613.65169049127\n"
     ]
    }
   ],
   "source": [
    "avg = np.mean(trips['numtrips'])\n",
    "print('Just using average={0} has RMSE of {1}'.format(avg, np.sqrt(np.mean((trips['numtrips'] - avg)**2))))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The mean here is about 400,000 and the root-mean-square-error (RMSE) in this case is about 52,000. In other words, if we were to estimate that there are 400,000 taxi trips on any given day, that estimate is will be off on average by about 52,000 in either direction.\n",
    "  \n",
    "Let's see if we can do better than this -- our goal is to make predictions of taxicab demand whose RMSE is lower than 52,000.\n",
    "\n",
    "What kinds of things affect people's use of taxicabs?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Weather data\n",
    "\n",
    "We suspect that weather influences how often people use a taxi. Perhaps someone who'd normally walk to work would take a taxi if it is very cold or rainy.\n",
    "\n",
    "One of the advantages of using a global data warehouse like BigQuery is that you get to mash up unrelated datasets quite easily."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "    <div class=\"bqtv\" id=\"3_153685830356\"><table><tr><th>usaf</th><th>wban</th><th>name</th><th>country</th><th>state</th><th>call</th><th>lat</th><th>lon</th><th>elev</th><th>begin</th><th>end</th></tr><tr><td>725030</td><td>14732</td><td>LA GUARDIA AIRPORT</td><td>US</td><td>NY</td><td>KLGA</td><td>40.779</td><td>-73.88</td><td>+0003.4</td><td>19730101</td><td>20180909</td></tr></table></div>\n",
       "    <br />(rows: 1, time: 1.2s,     2MB processed, job: job_vY7PhQb3F6GUScbyCXxB2kC9LB_d)<br />\n",
       "    <script src=\"/static/components/requirejs/require.js\"></script>\n",
       "    <script>\n",
       "      require.config({\n",
       "        paths: {\n",
       "          base: '/static/base',\n",
       "          d3: '//cdnjs.cloudflare.com/ajax/libs/d3/3.4.13/d3',\n",
       "          plotly: 'https://cdn.plot.ly/plotly-1.5.1.min.js?noext',\n",
       "          jquery: '//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min'\n",
       "        },\n",
       "        map: {\n",
       "          '*': {\n",
       "            datalab: 'nbextensions/gcpdatalab'\n",
       "          }\n",
       "        },\n",
       "        shim: {\n",
       "          plotly: {\n",
       "            deps: ['d3', 'jquery'],\n",
       "            exports: 'plotly'\n",
       "          }\n",
       "        }\n",
       "      });\n",
       "\n",
       "      require(['datalab/charting', 'datalab/element!3_153685830356', 'base/js/events',\n",
       "          'datalab/style!/nbextensions/gcpdatalab/charting.css'],\n",
       "        function(charts, dom, events) {\n",
       "          charts.render('gcharts', dom, events, 'table', [], {\"cols\": [{\"type\": \"string\", \"id\": \"usaf\", \"label\": \"usaf\"}, {\"type\": \"string\", \"id\": \"wban\", \"label\": \"wban\"}, {\"type\": \"string\", \"id\": \"name\", \"label\": \"name\"}, {\"type\": \"string\", \"id\": \"country\", \"label\": \"country\"}, {\"type\": \"string\", \"id\": \"state\", \"label\": \"state\"}, {\"type\": \"string\", \"id\": \"call\", \"label\": \"call\"}, {\"type\": \"number\", \"id\": \"lat\", \"label\": \"lat\"}, {\"type\": \"number\", \"id\": \"lon\", \"label\": \"lon\"}, {\"type\": \"string\", \"id\": \"elev\", \"label\": \"elev\"}, {\"type\": \"string\", \"id\": \"begin\", \"label\": \"begin\"}, {\"type\": \"string\", \"id\": \"end\", \"label\": \"end\"}], \"rows\": [{\"c\": [{\"v\": \"725030\"}, {\"v\": \"14732\"}, {\"v\": \"LA GUARDIA AIRPORT\"}, {\"v\": \"US\"}, {\"v\": \"NY\"}, {\"v\": \"KLGA\"}, {\"v\": 40.779}, {\"v\": -73.88}, {\"v\": \"+0003.4\"}, {\"v\": \"19730101\"}, {\"v\": \"20180909\"}]}]},\n",
       "            {\n",
       "              pageSize: 25,\n",
       "              cssClassNames:  {\n",
       "                tableRow: 'gchart-table-row',\n",
       "                headerRow: 'gchart-table-headerrow',\n",
       "                oddTableRow: 'gchart-table-oddrow',\n",
       "                selectedTableRow: 'gchart-table-selectedrow',\n",
       "                hoverTableRow: 'gchart-table-hoverrow',\n",
       "                tableCell: 'gchart-table-cell',\n",
       "                headerCell: 'gchart-table-headercell',\n",
       "                rowNumberCell: 'gchart-table-rownumcell'\n",
       "              }\n",
       "            },\n",
       "            {source_index: 1, fields: 'usaf,wban,name,country,state,call,lat,lon,elev,begin,end'},\n",
       "            0,\n",
       "            1);\n",
       "        }\n",
       "      );\n",
       "    </script>\n",
       "  "
      ],
      "text/plain": [
       "QueryResultsTable job_vY7PhQb3F6GUScbyCXxB2kC9LB_d"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%bq query\n",
    "SELECT * FROM `bigquery-public-data.noaa_gsod.stations`\n",
    "WHERE state = 'NY' AND wban != '99999' AND name LIKE '%LA GUARDIA%'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Variables\n",
    "\n",
    "Let's pull out the minimum and maximum daily temperature (in Fahrenheit) as well as the amount of rain (in inches) for La Guardia airport."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "%bq query -n wxquery\n",
    "SELECT EXTRACT (DAYOFYEAR FROM CAST(CONCAT(@YEAR,'-',mo,'-',da) AS TIMESTAMP)) AS daynumber,\n",
    "       MIN(EXTRACT (DAYOFWEEK FROM CAST(CONCAT(@YEAR,'-',mo,'-',da) AS TIMESTAMP))) dayofweek,\n",
    "       MIN(min) mintemp, MAX(max) maxtemp, MAX(IF(prcp=99.99,0,prcp)) rain\n",
    "FROM `bigquery-public-data.noaa_gsod.gsod*`\n",
    "WHERE stn='725030' AND _TABLE_SUFFIX = @YEAR\n",
    "GROUP BY 1 ORDER BY daynumber DESC"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>daynumber</th>\n",
       "      <th>dayofweek</th>\n",
       "      <th>mintemp</th>\n",
       "      <th>maxtemp</th>\n",
       "      <th>rain</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>365</td>\n",
       "      <td>5</td>\n",
       "      <td>46.0</td>\n",
       "      <td>48.2</td>\n",
       "      <td>0.17</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>364</td>\n",
       "      <td>4</td>\n",
       "      <td>34.0</td>\n",
       "      <td>48.0</td>\n",
       "      <td>0.13</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>363</td>\n",
       "      <td>3</td>\n",
       "      <td>33.8</td>\n",
       "      <td>46.9</td>\n",
       "      <td>0.37</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>362</td>\n",
       "      <td>2</td>\n",
       "      <td>39.0</td>\n",
       "      <td>62.1</td>\n",
       "      <td>0.02</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>361</td>\n",
       "      <td>1</td>\n",
       "      <td>46.0</td>\n",
       "      <td>62.6</td>\n",
       "      <td>0.14</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   daynumber  dayofweek  mintemp  maxtemp  rain\n",
       "0        365          5     46.0     48.2  0.17\n",
       "1        364          4     34.0     48.0  0.13\n",
       "2        363          3     33.8     46.9  0.37\n",
       "3        362          2     39.0     62.1  0.02\n",
       "4        361          1     46.0     62.6  0.14"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "query_parameters = [\n",
    "  {\n",
    "    'name': 'YEAR',\n",
    "    'parameterType': {'type': 'STRING'},\n",
    "    'parameterValue': {'value': 2015}\n",
    "  }\n",
    "]\n",
    "weather = wxquery.execute(query_params=query_parameters).result().to_dataframe()\n",
    "weather[:5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Merge datasets\n",
    "\n",
    "Let's use Pandas to merge (combine) the taxi cab and weather datasets day-by-day."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>daynumber</th>\n",
       "      <th>dayofweek</th>\n",
       "      <th>mintemp</th>\n",
       "      <th>maxtemp</th>\n",
       "      <th>rain</th>\n",
       "      <th>numtrips</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>365</td>\n",
       "      <td>5</td>\n",
       "      <td>46.0</td>\n",
       "      <td>48.2</td>\n",
       "      <td>0.17</td>\n",
       "      <td>339939</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>364</td>\n",
       "      <td>4</td>\n",
       "      <td>34.0</td>\n",
       "      <td>48.0</td>\n",
       "      <td>0.13</td>\n",
       "      <td>319649</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>363</td>\n",
       "      <td>3</td>\n",
       "      <td>33.8</td>\n",
       "      <td>46.9</td>\n",
       "      <td>0.37</td>\n",
       "      <td>311730</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>362</td>\n",
       "      <td>2</td>\n",
       "      <td>39.0</td>\n",
       "      <td>62.1</td>\n",
       "      <td>0.02</td>\n",
       "      <td>301398</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>361</td>\n",
       "      <td>1</td>\n",
       "      <td>46.0</td>\n",
       "      <td>62.6</td>\n",
       "      <td>0.14</td>\n",
       "      <td>268841</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   daynumber  dayofweek  mintemp  maxtemp  rain  numtrips\n",
       "0        365          5     46.0     48.2  0.17    339939\n",
       "1        364          4     34.0     48.0  0.13    319649\n",
       "2        363          3     33.8     46.9  0.37    311730\n",
       "3        362          2     39.0     62.1  0.02    301398\n",
       "4        361          1     46.0     62.6  0.14    268841"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data = pd.merge(weather, trips, on='daynumber')\n",
    "data[:5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exploratory analysis\n",
    "\n",
    "Is there a relationship between maximum temperature and the number of trips?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/envs/py3env/lib/python3.5/site-packages/matplotlib/font_manager.py:1320: UserWarning: findfont: Font family ['sans-serif'] not found. Falling back to DejaVu Sans\n",
      "  (prop.get_family(), self.defaultFamily[fontext]))\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f6670d00a20>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "j = data.plot(kind='scatter', x='maxtemp', y='numtrips')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The scatterplot above doesn't look very promising. There appears to be a weak downward trend, but it's also quite noisy.\n",
    "\n",
    "Is there a relationship between the day of the week and the number of trips?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/envs/py3env/lib/python3.5/site-packages/matplotlib/font_manager.py:1320: UserWarning: findfont: Font family ['sans-serif'] not found. Falling back to DejaVu Sans\n",
      "  (prop.get_family(), self.defaultFamily[fontext]))\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f667116da58>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "j = data.plot(kind='scatter', x='dayofweek', y='numtrips')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Hurrah, we seem to have found a predictor. It appears that people use taxis more later in the week. Perhaps New Yorkers make weekly resolutions to walk more and then lose their determination later in the week, or maybe it reflects tourism dynamics in New York City.\n",
    "\n",
    "Perhaps if we took out the <em>confounding</em> effect of the day of the week, maximum temperature will start to have an effect. Let's see if that's the case:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/envs/py3env/lib/python3.5/site-packages/matplotlib/font_manager.py:1320: UserWarning: findfont: Font family ['sans-serif'] not found. Falling back to DejaVu Sans\n",
      "  (prop.get_family(), self.defaultFamily[fontext]))\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f66700f84e0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "j = data[data['dayofweek'] == 7].plot(kind='scatter', x='maxtemp', y='numtrips')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Removing the confounding factor does seem to reflect an underlying trend around temperature. But ... the data are a little sparse, don't you think?  This is something that you have to keep in mind -- the more predictors you start to consider (here we are using two: day of week and maximum temperature), the more rows you will need so as to avoid <em> overfitting </em> the model."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Adding 2014 and 2016 data\n",
    "\n",
    "Let's add in 2014 and 2016 data to the Pandas dataframe.  Note how useful it was for us to modularize our queries around the YEAR."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>daynumber</th>\n",
       "      <th>dayofweek</th>\n",
       "      <th>mintemp</th>\n",
       "      <th>maxtemp</th>\n",
       "      <th>rain</th>\n",
       "      <th>numtrips</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>1096.000000</td>\n",
       "      <td>1096.000000</td>\n",
       "      <td>1096.000000</td>\n",
       "      <td>1096.000000</td>\n",
       "      <td>1096.000000</td>\n",
       "      <td>1096.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>183.166971</td>\n",
       "      <td>4.005474</td>\n",
       "      <td>48.195073</td>\n",
       "      <td>66.151825</td>\n",
       "      <td>0.117272</td>\n",
       "      <td>403642.694343</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>105.510927</td>\n",
       "      <td>2.000449</td>\n",
       "      <td>18.031228</td>\n",
       "      <td>18.484065</td>\n",
       "      <td>0.320836</td>\n",
       "      <td>63767.524397</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>21.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>78133.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>92.000000</td>\n",
       "      <td>2.000000</td>\n",
       "      <td>35.100000</td>\n",
       "      <td>51.950000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>363809.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>183.000000</td>\n",
       "      <td>4.000000</td>\n",
       "      <td>48.900000</td>\n",
       "      <td>68.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>402184.500000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>274.250000</td>\n",
       "      <td>6.000000</td>\n",
       "      <td>64.400000</td>\n",
       "      <td>82.900000</td>\n",
       "      <td>0.050000</td>\n",
       "      <td>447099.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>366.000000</td>\n",
       "      <td>7.000000</td>\n",
       "      <td>82.000000</td>\n",
       "      <td>99.000000</td>\n",
       "      <td>4.880000</td>\n",
       "      <td>574530.000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         daynumber    dayofweek      mintemp      maxtemp         rain  \\\n",
       "count  1096.000000  1096.000000  1096.000000  1096.000000  1096.000000   \n",
       "mean    183.166971     4.005474    48.195073    66.151825     0.117272   \n",
       "std     105.510927     2.000449    18.031228    18.484065     0.320836   \n",
       "min       1.000000     1.000000     1.000000    21.000000     0.000000   \n",
       "25%      92.000000     2.000000    35.100000    51.950000     0.000000   \n",
       "50%     183.000000     4.000000    48.900000    68.000000     0.000000   \n",
       "75%     274.250000     6.000000    64.400000    82.900000     0.050000   \n",
       "max     366.000000     7.000000    82.000000    99.000000     4.880000   \n",
       "\n",
       "            numtrips  \n",
       "count    1096.000000  \n",
       "mean   403642.694343  \n",
       "std     63767.524397  \n",
       "min     78133.000000  \n",
       "25%    363809.000000  \n",
       "50%    402184.500000  \n",
       "75%    447099.000000  \n",
       "max    574530.000000  "
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data2 = data # 2015 data\n",
    "for year in [2014, 2016]:\n",
    "    query_parameters = [\n",
    "      {\n",
    "        'name': 'YEAR',\n",
    "        'parameterType': {'type': 'STRING'},\n",
    "        'parameterValue': {'value': year}\n",
    "      }\n",
    "    ]\n",
    "    weather = wxquery.execute(query_params=query_parameters).result().to_dataframe()\n",
    "    trips = taxiquery.execute(query_params=query_parameters).result().to_dataframe()\n",
    "    data_for_year = pd.merge(weather, trips, on='daynumber')\n",
    "    data2 = pd.concat([data2, data_for_year])\n",
    "data2.describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/envs/py3env/lib/python3.5/site-packages/matplotlib/font_manager.py:1320: UserWarning: findfont: Font family ['sans-serif'] not found. Falling back to DejaVu Sans\n",
      "  (prop.get_family(), self.defaultFamily[fontext]))\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZcAAAELCAYAAAAVwss1AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvNQv5yAAAIABJREFUeJzt3X+cXXV95/HXkElCfgzOgEOkCS6hhg8qVioIadkHoLUQ1DXQCrq6EJDVfVBUWLcWbH2ARdzFbhelrRvXFUoStYDYSLaCgaLA2gqN/FoV/MQIlAw/wkAmcfKDSSaZ/eN8b3Ln5M79ec6559z7fj4e85h7zj0/vvfcc7+f769zTs/ExAQiIiJJOqjdCRARkc6j4CIiIolTcBERkcQpuIiISOIUXEREJHEKLiIikrjeNDduZv3A14HjgAngI4ADtwJHAc8A57n7iJn1ADcA7wZ2ABe6+yNhO8uAz4bNXuvuK8L8E4CbgVnAncBl7j5hZodW2kean1VERPZLu+ZyA/B9dz8WeCvwJHAlcK+7LwLuDdMAZwGLwt/HgOUAIVBcDZwMnARcbWYDYZ3lYdnSekvC/Kn2ISIiGUgtuJjZIcCpwI0A7r7L3bcAS4EVYbEVwNnh9VJgpbtPuPuDQL+ZHQGcCdzj7ptD7eMeYEl47xB3/7G7TwArY9uqtA8REclAmjWXo4Fh4G/N7FEz+7qZzQHmufsLAOH/4WH5+cDGsvWHwrxq84cqzKfKPkREJANp9rn0Am8DPuHuD5nZDVRvnuqpMG+iiflNGR/fM9HbO63Z1UVEulWlvDjV4DIEDLn7Q2H6dqLgssnMjnD3F0LT1ktlyx9Ztv4C4Pkw//TY/PvC/AUVlqfKPqY0MrKjgY/WusHBPoaHRzPdZzOUzuQVJa1KZ7KKkk5oLK2Dg30V56fWLObuLwIbzczCrN8DngDWAMvCvGXAHeH1GuACM+sxs8XA1tCktRY4w8wGQkf+GcDa8N6omS0OI80uiG2r0j5ERCQDqQ5FBj4BfNPMZgBPARcRBbTbzOxi4Fng3LDsnUTDkDcQDUW+CMDdN5vZ54F1Yblr3H1zeH0J+4ci3xX+AK6bYh8iIpKBHt1yPzI8PJrpgShKFVnpTF5R0qp0Jqso6YSGm8Uq9rnoCn0REUmcgouIiCROwUVERBKXdoe+iATbduxi1d3r2bJ9F/1zZnD+mccwd9aMdidLJBUKLiIZWXX3etb9YvIlV5ecfVybUiOSLjWLiWRkeMvOqtMinUTBRSQjg/2zqk6LdBI1i4lk5PwzjwGY1Oci0qkUXERiSh3vw1t2Mtg/K7GO97mzZnDJ2ccV6mI6kWYpuIjElHe8P/NiFATU8S7SGPW5iMSo412kdaq5dKG0mn06xWD/rH01ltK0iDRGwaULqdmnulJHeyn4nnPqQpZ/92cKxiINUHApgKRrGmr2qa7U8V6y/Ls/UzAWaZCCSwEkXdNQs09j6gnGamoUmUzBpQCSrmnEm310vUV19QTjIjc1KjBKGhRcCiDpmka82afb1cpc6wnGRW5qLHJglPxScCkA1TTSVStzrScYZ9HUmFYNI+nAqJqQgIJLIaimka4kMtcsCgBp1TCSDoyqCQkouEiKilKCTSJzTaMAED9+L76yfdL7STW9JR0Yi9xEKMlRcJHUFKUEm9dmx/jxG+ibOen9pJrekg6MGo0ooODSkqKUzNulKCXYvDY7xo9X3+xe3jD/NbkLgnF5DdaSLQWXFhSlZN4uKsG2Jn785g3MKcT5ladgrQJg+yi4tKAoJfN2UQm2NTp+rVMBsH0UXFqgknl1eSrBNiIvpd2iHr88UQGwfRRcWlCUkmVeMsuiUGm3c6gA2D4KLi0oSslSmWVjVNrtHEUpAHYiBZcCaLXmkVVmmdcaUqPpUmm3urx+z5UUpQDYiRRcCqDVmkdWmWVea0iNpuucUxey4bmtbN+5mzkHT+ec0xZmks68igeT3eN7eGzDK0Dz33ORApQ0R8GlAFqteWTVNNBoOpvJYJpZp9F0rX7gaUZGxwDYtW2M1fc/nUmQzGuGGw/Os2dOm/R+MzXhvBZEJDkKLgXQas0jq6aB/rkzqk7H3XTnk5NKwLvH9/DJ97+16jrNZEqNHr929bm0K8OtFdTit53Zu3di0nQzNWH1a3W+VIOLmT0DjAJ7gHF3P9HMDgVuBY4CngHOc/cRM+sBbgDeDewALnT3R8J2lgGfDZu91t1XhPknADcDs4A7gcvcfWKqfaT5WdOUdM0jrRJyT09P1em49Ru3VJ2upJlMqdHj164+l7wGtW2vjk9a/uCZvbzlN/tbOh+zOsZ5rQ12gyxqLu9w95fLpq8E7nX368zsyjB9BXAWsCj8nQwsB04OgeJq4ERgAnjYzNaEYLEc+BjwIFFwWQLcVWUfuTfVjyHJEmxaJeRSU1LJK1t31nj2fDz4VA9G0Fym1Ojxa9cIo7wGtb7ZvZO+20PmTG/5fMnqGOe1+a0bgl47msWWAqeH1yuA+4gy/qXASnefAB40s34zOyIse4+7bwYws3uAJWZ2H3CIu/84zF8JnE0UXKbaR9uVTqot23fRP2fGASdVFj+GtErI8cxxdOc4z1b5LHZkP49u2F/usNf319xHFplSu0YYZfHZKmVqtYLavIE5PLtp+6TpVjVzjLPob8tKXoNektIOLhPA3WY2Afwvd/8aMM/dXwBw9xfM7PCw7HxgY9m6Q2FetflDFeZTZR9tV35SlZSfVFn8GNIqIcczxxdf2T6pxBv/LBe951h6165vKDNtNFMqUgkxi6BWKVOrFdTycq1IFv1tWclr0EtS2sHlFHd/PmTu95jZL6osW6lNZKKJ+U0ZGJhNb++02gu2aMv2XQdMDw727ZteMK9v0o9hwby+Se8n4eKlb+HpF/6J0R276Js9g4uXvoXBwblTLl/v/geBqz76O/umv7hyHRuH95d4458lvnyrKqXzppXrJmVIM2f2csUFb09sn81K+jutV6Xzb+HrD5vyexgc7Ev8e2pWtd/OVMfz8g+dwPLvPM6mzTuYd+hsLvnDt3LInPYVLkrpzOJ33qpW05NqcHH358P/l8xsNXASsMnMjgg1iiOAUjF+CDiybPUFwPNh/umx+feF+QsqLE+VfUxpZGRHg5+uOf2xE7t/zgyGh/efZOedfjRjY+P7SonnnX70pPeTcOMdP+Plra8CMLb1VW6846ecf8YxFUv4g4N9Te8/i89SMlU6hzaNHjCdVhrq1coxbVWt869cs+lMq7Y4VdprpfMjZx277/XYjjGGd4xNuWyaytOZ5W+jGY1891MFodSCi5nNAQ5y99Hw+gzgGmANsAy4Lvy/I6yyBvi4md1C1KG/NQSHtcB/NbOBsNwZwGfcfbOZjZrZYuAh4ALgr8u2VWkfbVdqUijvcymXRdNIpSp5Gm3Aebg6Ok/NIrX627JQ5Mcx56V5Lgl5+G2kLc2ayzxgtZmV9vMtd/++ma0DbjOzi4FngXPD8ncSDUPeQDQU+SKAEEQ+D6wLy11T6twHLmH/UOS7wh9EQaXSPtqudFK1s/RaKcPt1DbgPGVItfrbstCuwktcM7WbVtNepP63TpBacHH3p4ADrohz91eA36swfwK4dIpt3QTcVGH+T4ADzrap9tEtav2IKmW4q9auz00JP0l5KiEmHcDzmlnWU1tsx2ipbhihlSe6Qr8D1foRVcpw81TC71RJN9HlNbOs51xqR025U2vneaXg0oGa+RHlqYTfqWr1tzUqr5llpXMpXssamDuTZ8i2ppyn/rduoODSgXRrjXxKur+tSJllvJZ1/BsO4+3HHp5pTVm182wpuHSgbr+1RlbaHVyLlFnGa1Vbtu3iqguzvd5ItfNsKbh0oKx+RHltlslKu4NrkTLLeC2rf+6MGvedy692FyqKQsFFmlakZpk0dHtwbUS8ljW+Z2/DgTkvmXq7CxVFoeAiTSvKowDS0i3BNYnvJV7LuubmdZPerycw5yVTV6GiPgou0rSiPAogLUXq82hFGt9LM4E5L5l6txQqWqXgIrmRl8yjHkWrZbUije+lmcCcl0y9WwoVrVJwkYracR+svGQe9WhHLatdAS2N76WZWm9eMvUiDaRoJwUXqagd98E659SFbHhuK9t37mbOwdM557SFqe6vFe2oZbWr2VCZujRDwSVFRW46aUfmufqBp/c9XGzXtjFW3/90bjOTdtSy2tVsqExdmqHgkqKidVCXqyfzTDp4ppV5phHk21Ga76RrRdqhyIW9IlJwaUGtk7VIHdRx9dwHK+ngmVZtoFOeVZPEtSJZyGsmftOdT/LYhleA6HjtHt/DJ99/wI3bJSEKLi2olWkVqYM6rp77YCUdPNOqDbQjyKeRwSZxrUgWsqqxNzroZP3GLVWnq+0jb4GyCBRcWlAr08pLR2hakg6eadUG2hHks8hg81p4qfS7SCKTjm9j9/iefTWRkmp3Yx7btTe2xZ6a+yxy03a7Kbi0oNaPu9M7QosyuiuNIN9Mk2jSw7srfa48lLQr/S6SyKTj25g9c9qk9yvV3CqNeiyx1/cfMC9+/DaNbK+5D6lMwaUFnV4zqaUoo7vSCPLNNIk2Orw7ntGdc+pCVj/w9KTzLb7+X3/n//HoL1/el67xPXv5xB/+VmsftkGVfhfX3/r4pGWayaQPXGdyzaNSzS2+zuyZvRw+MGvK32v8e+2fM33S+wN9MxtOd7dScGlBp9dMainygIVWNdMk2mgGG8/oNjy3dV8wL3VIT++dNmkf/uzkfoT4dBYq/S6aacKr9YAxe30/vdMOqjroJL7fNy88tOpvNv6dvLprfNL0xMREzXRLRMFFmtY/d0bV6U4Wz7S2bt/Ftp279jVBJZHBxjO67Tt3T5pev3ELO8b2AJRtN575pZ8Z1tMU10wtv54HjM2dNWPfoJNtO3YdMDS70f3Gv6ODDpoG7A8wW7btquuYiIKLtKCnp6fqdCc7/8xjJtUkRkbHWLV2fdVScaOPOY5ndHNmTWdX2F9k8vEe3rKTY47sn9TJfcyRB/YrJK2e/pRmavmbNk/u79g8+iqfu+jkhtPRyH4PGO49vpdHN7y87/28DJooAgUXadrIpIzuwOk8dC6nZe6sGbxmzoxJn7lWM1ejjzmOZ3TnnLaQ1fc/XTXjO//MY1i1dn2m/YBpNY+O7hivOp1GOuJBcNvOXfRmfDw7hYKLNK1WM0+nD+NMeyhwpdJ+rYwviX7ARke1pXUc5s7qZWTb/uA99+Dq2VW7brDZyYWoVii4SNNqtWd3eod/ux+WltaAkkZHtaU1avJ1h81h4/D2SdPVtGv0ZqcXopql4CJNq5W55fUiv6R06sPSGi0UpBXkGg0W7Rq92emFqGYpuEhquv06oEbFM6VNm7e35caUeSkUHND/UWE0WCPHI6nmq/h24qMkO60Q1SwFlxaorbW6br8OqFHxTH105zjPtvH5LfWOastKqzW7pGqG8e389qLXHjBEWhRcWpKXZgzpDPGa3ouvbG9oNFo96ikQNTqqLSutNj/Vs349xye+3sjoGFdd+PaG0tINFFxa0O1trUWpuTWaznZ9rnhNb/l3fzapQzuJ5pYiF4haba6rZ/16jk9emg3zTsGlBd1+khUlo2o0nXn5XGn0WRW5QNTq8ahn/XqOj/oS66Pg0oJuP8niV1DH7yCbhCRqEY1mqHnJgNPosypygajV41HP+vHjM9A3s+IggjwWovIm9eBiZtOAnwDPuft7zWwhcAtwKPAIcL677zKzmcBK4ATgFeAD7v5M2MZngIuBPcAn3X1tmL8EuAGYBnzd3a8L8yvuI+nP1u0nWaNXUDcjiVpEoxlqkTPgWtrx+IEiiR+fnWO7236X6aLKouZyGfAkcEiY/iLwJXe/xcy+ShQ0lof/I+7+BjP7YFjuA2b2JuCDwJuB3wD+0cxKv4ivAL8PDAHrzGyNuz9RZR+SoEavoG5GErWIA26jcurCqkNaO7lG2kyBqFbwaKYAkNeAFD8+H//SA5Peb8ddposq1eBiZguA9wBfAD5lZj3AO4EPhUVWAJ8jyviXhtcAtwN/E5ZfCtzi7mPA02a2ATgpLLfB3Z8K+7oFWGpmT1bZhySo0Suom5FELaJSR3m1zLDba6RxtYJHMwWAvPRr1Zb9XaY7Rdo1ly8DfwL0henDgC3uXmo/GQLmh9fzgY0A7j5uZlvD8vOBB8u2Wb7Oxtj8k2vsQxKURQlfndrtV+t4NVMAKMp30I67THeK1IKLmb0XeMndHzaz08PsSvdkn6jx3lTzD2pw+aoGBmbT2zut1mKJGhzsq71QArZu38VXv/M4mzbvYN6hs7nkD9/KIXPqb4KYKp2DwFUf/Z2EUjnFvhvYR73Hc8G8vkmZ4YJ5fZl9FyVZ769Zg4N9NY/X5R86geUNnl9JfwdpHc9PX3BSw5+tmqJ879B6WtOsuZwCvM/M3g0cTNTn8mWg38x6Q81iAfB8WH4IOBIYMrNe4DXA5rL5JeXrVJr/cpV9TGlkZEdTH7JZWV6gVt4M9MuNWxgbG6+7CSJvF9JNpZF0nnf60YyNje+rDZ13+tGZfsZmj2nW/RSldNZzvD5y1rH7Xo/tGGN4x1h8c5PUs816P2/a52ijn20qjaSz3X1SjaR1qiCUWnBx988AnwEINZc/dvcPm9m3gfcTjeZaBtwRVlkTpn8c3v+Bu0+Y2RrgW2Z2PVGH/iLgX4hqKIvCyLDniDr9PxTW+eEU++hK8SaHF19pzz2r8qKofSr19FOkkSmlcbzq2WY7+mWyytTTGCSRN+24zuUK4BYzuxZ4FLgxzL8RWBU67DcTBQvc/edmdhvwBNHzRi919z0AZvZxYC3RUOSb3P3nNfbRleJt4tteHS/8iduN6umn6IRMqaQd/TJ/e9cvEh96XOn5OGkMksibTIKLu98H3BdeP8X+0V7ly7wKnDvF+l8gGnEWn38ncGeF+RX30a3ineKbRpK/Z5Wkr56O87zcWTmumRpBO643ig81TmLocaXn46QxSCJvdIV+F6g0FPfZTcnes0qSF8+QzzltIVB95Fz89u9btu/i2Zei77qdNZlmalTtud4o+aHHlQJJreDRCddaKbh0oU44cbtBMxlyT8/kwZK7d++dNN2uWmqtkvpUNZusA2FSQ4/LP8/WbZNvDlL+m5vqN1jUfsFydQUXM/sUcKO7bzWzVcDbiW7DcneqqZNUdMKJ2w2aaXcvb+6EA4NNu2qptUrqlQLp+WccM7nmdupCVj/wdKpNfB95zxtZtXZ9ywWveFPYQN9MXts/a1+fSzf8BuutuVzo7teb2TuAw4GPAH8FKLiIpKSZdvf4Ovb6fnqnHdT2WmqtknqlQBoPOBue27oveKbVxJdUph//PK+ZM4PrLz+tEMP6k1JvcNkT/r8D+Ka7/7OZVbqIUUQS0kzzZaV18jDMvFamXSmQxjPo7Tt3T5rOoomv2aHJndAh36p6g8tOM/sz4MPAKeGeX+0/Y0U6WDPPkC9qc0uloLhq7fpJGfScWdPZVdbsl0WG3ezQ7kYKBu2+YDItdTeLAX8EfNrdXzSz3wS+mVqqROQAnXQNS1yloHjA3axPW8jq+5/OtImv2etNGgnynfq91hVc3H09cLmZzTWzue7+K+C/pZs0ESnXCRfWNaJSBp304wJqyaJ5q1O/13pHix0LrALeAkyY2U+JHsDlaSZORPZTO37jWq0VZDFsv1O/13qbxW4G/poowEDU97ICWJxCmkSkAl2f1LhGawWVajppN1F16vdab3CZ7u4ry6a/YWaXp5EgEamsqJ317dRorSBe09k9vofpvdNS7Wxv1/ea9kCCeoPL42b2b939RwBmdgqTH+AlIpI7jdYK4jWb9Ru3sGMsuhKjkzrbIf2BBPUGl7cBy8IdiwHeADxmZv8C4O66SaSI5E6jtYJ4TSf+7ME0OtvbNRQ57YEE9QaXyxLdq4hIDsVrOuPje3l0w8v73k+js71dQ5HTHkhQ71Dk+xPdq4hIDh1w4erOXfQmcK+xato1FDntgQRVg4uZfdHdrwhPjzzg3tPufl6iqRGRunXqld3t1I7RYu0aipz2QIJaNZcfhf//kFoKRKQpnXpldzu145h25VBkd/8/ZjYNONrdr84oTSJSh069srud2nFMsxyKnGVtt+adjcPz6k9NZe8i0rR480mnXNndTp1+TEs1s2deHGXdL15i1dr1qe2r3tFi3zOzPwZWAttKM919RyqpEpGaOrU5pZ0OuFnmqQtr3om6SLKsmdUbXP6i7P8E0eDvCWBaGokSkdp0xX7ranXgL//uzzqqXyvLwQP1DkXWg8FEpOPU6sDPoqSfZT9IlrXdeu+K/GV3v7zWPBGRIqkVPLIo6Wc5Qi3L2m69zWKVOvRPSzIhInmh60e6R63gkVZJv/wce2mkM0f91bqI8lzgPOAoM7ut7K3XAOrMl46k60e6R63gkVZJv/wci+uUEWq1ai7rge8BJ4X/Jb8G7k0rUSLtpOtHuke7BkXEz6nZM6dx+MDsjhr1V+siyseJbre/xt03Z5Qmkbbq1CcDSn7Ez7E3Lzys42rH9fa59JrZNUS32t+3ju4tJuU6pa9C149Iqyr9FgbL3u+Gc6ze4HIH8Ajwj8Ce9JIjRdYpfRW6fkRaVem3cNVHf2ff+91wjtUbXGa7+6WppkQKT30VkmdZ1qxr/RY6pZZfTb0XRz5kZm9JNSVSeJ1+XyYptizvq1Xrt5BlWtql3prLV4EHzGwj8GppZrXHG5vZwcADwMywn9vd/WozWwjcAhxK1NR2vrvvMrOZRPcuOwF4BfiAuz8TtvUZ4GKiJrlPuvvaMH8JcAPRbWi+7u7XhfkV91HnZ5UmdUM7shRXljXrWr+Fbqjl1xtcvgF8gSijrrfPZQx4p7tvM7PpwI/M7C7gU8CX3P0WM/sqUdBYHv6PuPsbzOyDwBeBD5jZm4APAm8GfgP4RzMrfVNfAX4fGALWhVFtT4R1K+1DUtQN7chSXFmOAqz1W+iGEYn1BpdX3f0vG9mwu0+w/w7K08PfBPBO4ENh/grgc0QZ/9LwGuB24G/MrCfMv8Xdx4CnzWwD0XU3ABvc/SkAM7sFWGpmT1bZh4h0qTzVrPOUlrTUG1y+b2ZL3P37jWw8PGjsYaIhzF8BfgVscffxsMgQMD+8ng9sBHD3cTPbChwW5j9YttnydTbG5p8c1plqHyIN64bO126Qp5p1ntKSlnqDy0eBK81slKi5qweYcPfDq60UHjR2vJn1A6uBN1ZYbCL875nivanmVxqMUG35qgYGZtPbm+0TBAYH+zLdX7O6PZ03rVw3aVjpzJm9XHHB21vaZrcf06QpnclrNa31BpcTW9mJu28xs/uAxUC/mfWGmsUC4Pmw2BBwJDBkZr1E9y/bXDa/pHydSvNfrrKPKY2MZHurtMHBPoaHR2sv2GZKJwxtGj1gupV96ZgmS+lMXiNpnSoI1fs8l3+tP1kRMxsEdofAMgt4F1FH+w+B9xON5lpGdIEmwJow/ePw/g/cfcLM1gDfMrPriTr0FwH/QlRDWRRGhj1H1On/obDOVPsQaVg3dL6KJK3e57kMU6FpqUaz2BHAitDvchBwm7v/g5k9AdxiZtcCjwI3huVvBFaFDvvNRMECd/95uCPzE8A4cGlobsPMPg6sJRqKfJO7/zxs64op9iHSsG7ofBVJWs/ERM3uCMzs35RNHgx8mKhW8vm0Epa14eHR2gciQUWpIieZzjQ7xotyPKE4aVU6k1WUdELDzWKV+rmbbha7ysx+AHRMcJH0dcq9x0Sktnpv/zKJmR0NHJVsUqTTdcNVySISaabPZVpY77K0EiWdSR3jIt2jmaHI48CLpU51kXqpY1ykezTU52JmM8I6M80Md8/24hAptG64KlnyS3dayFa9zWJ/APwV0fBiCFfoEzWRiYjkngaUZKveZrG/AM4DHnT3vSmmR0SkKbVqJhpQkq16g8tmd//nVFMiItKCWjUTDSjJVr3BZbWZXQLcyuSHhanPRURyoVbNRANKslVvcPlC+P8V9t95WH0uIpIbtWomGlCSrXpHizV1saWISFZUM8mXemsuIrmg4aQypUzvDii1KLhIoWg4qUxF50a+qLlLCkXDSWUqOjfyRcFFCiXeSavhpFKicyNf1CwmhaJOW5mKzo18UXCRQtFwUpmKzo18UXARKQiNlJMiUXARKQiNhpIiUYe+SEFoNJQUiYKLSEFoNJQUiZrFRApCo6GkSBRcRApCo6GkSNQsJiIiiVNwERGRxCm4iIhI4hRcREQkcQouIiKSOAUXERFJnIKLiIgkLrXrXMzsSGAl8DpgL/A1d7/BzA4FbgWOAp4BznP3ETPrAW4A3g3sAC5090fCtpYBnw2bvtbdV4T5JwA3A7OAO4HL3H1iqn2k9VlFRGSyNGsu48B/cfc3AouBS83sTcCVwL3uvgi4N0wDnAUsCn8fA5YDhEBxNXAycBJwtZkNhHWWh2VL6y0J86fah4iIZCC14OLuL5RqHu4+CjwJzAeWAivCYiuAs8PrpcBKd59w9weBfjM7AjgTuMfdN4faxz3AkvDeIe7+Y3efIKollW+r0j5ERCQDmfS5mNlRwG8DDwHz3P0FiAIQcHhYbD6wsWy1oTCv2vyhCvOpsg8REclA6vcWM7O5wHeAy93912Y21aI9FeZNNDG/KQMDs+ntndbs6k0ZHOzLdH/NUjqTV5S0Kp3JKko6ofW0phpczGw6UWD5prv/fZi9ycyOcPcXQtPWS2H+EHBk2eoLgOfD/NNj8+8L8xdUWL7aPqY0MrKjkY/WssHBPoaHRzPdZzOUzuQVJa1KZ7KKkk5oLK1TBaHUmsXC6K8bgSfd/fqyt9YAy8LrZcAdZfMvMLMeM1sMbA1NWmuBM8xsIHTknwGsDe+NmtnisK8LYtuqtA8REclAmjWXU4DzgZ+a2WNh3p8C1wG3mdnFwLPAueG9O4mGIW8gGop8EYC7bzazzwPrwnLXuPvm8PoS9g9Fviv8UWUfIiKSgZ6Jiaa7KTrK8PBopgeiKFVkpTN5RUmr0pmsoqQTGm4Wq9T/rSv0RUQkeQouIiKSOAUXERFJnIKLiIgkTsFFREQSp+AiIiKJU3AREZHEKbhhGUIRAAAKJUlEQVSIiEjiFFxERCRxCi4iIpI4BRcREUmcgouIiCROwUVERBKn4CIiIolTcBERkcQpuIiISOIUXEREJHEKLiIikjgFFxERSZyCi4iIJE7BRUREEqfgIiIiiVNwERGRxCm4iIhI4hRcREQkcQouIiKSOAUXERFJnIKLiIgkTsFFREQSp+AiIiKJU3AREZHE9aa1YTO7CXgv8JK7HxfmHQrcChwFPAOc5+4jZtYD3AC8G9gBXOjuj4R1lgGfDZu91t1XhPknADcDs4A7gcvcfWKqfaT1OUVE5EBp1lxuBpbE5l0J3Ovui4B7wzTAWcCi8PcxYDnsC0ZXAycDJwFXm9lAWGd5WLa03pIa+xARkYykFlzc/QFgc2z2UmBFeL0COLts/kp3n3D3B4F+MzsCOBO4x903h9rHPcCS8N4h7v5jd58AVsa2VWkfIiKSkaz7XOa5+wsA4f/hYf58YGPZckNhXrX5QxXmV9uHiIhkJLU+lwb1VJg30cT8pg0MzKa3d1orm2jY4GBfpvtrltKZvKKkVelMVlHSCa2nNevgssnMjnD3F0LT1kth/hBwZNlyC4Dnw/zTY/PvC/MXVFi+2j6qGhnZ0eBHac3gYB/Dw6OZ7rMZSmfyipJWpTNZRUknNJbWqYJQ1s1ia4Bl4fUy4I6y+ReYWY+ZLQa2hiattcAZZjYQOvLPANaG90bNbHEYaXZBbFuV9iEiIhlJcyjy3xHVOl5rZkNEo76uA24zs4uBZ4Fzw+J3Eg1D3kA0FPkiAHffbGafB9aF5a5x99IggUvYPxT5rvBHlX2IiEhGeiYmWuqq6BjDw6OZHoiiVJGVzuQVJa1KZ7KKkk5ouFmsUh+4rtAXEZHkKbiIiEji8jIUuWts27GLVXevZ8v2XfTPmcH5Zx7D3Fkz2p0sEZFEKbhkbNXd61n3i8mjoy85+7g2pUZEJB1qFsvY8JadVadFRDqBgkvGBvtnVZ0WEekEahbL2PlnHgMwqc9FRKTTKLhkbO6sGVxy9nGFGvMuItIoNYuJiEjiFFxERCRxCi4iIpI4BRcREUmcgouIiCROwUVERBKnW+6LiEjiVHMREZHEKbiIiEjiFFxERCRxCi4iIpI4BRcREUmcgouIiCROd0VOmZkdDDwAzCQ63re7+9VmthC4BTgUeAQ43913tS+lETObBvwEeM7d35vjdD4DjAJ7gHF3P9HMDgVuBY4CngHOc/eRNiURADPrB74OHAdMAB8BnByl08wspKfkaOAqYCU5SieAmf1n4D8SHcufAhcBR5DPc/Qy4KNAD/C/3f3LeThHzewm4L3AS+5+XJhXMV1m1gPcALwb2AFc6O6P1LMf1VzSNwa8093fChwPLDGzxcAXgS+5+yJgBLi4jWksdxnwZNl0XtMJ8A53P97dTwzTVwL3hrTeG6bb7Qbg++5+LPBWomObq3R65Hh3Px44gSgTWU3O0mlm84FPAieGTHEa8EFyeI6a2XFEgeUkou/9vWa2iHwc05uBJbF5U6XrLGBR+PsYsLzenSi4pMzdJ9x9W5icHv4mgHcCt4f5K4Cz25C8ScxsAfAeopI2odSSu3RWsZQojZCDtJrZIcCpwI0A7r7L3beQs3TG/B7wK3f/V/KZzl5glpn1ArOBF8jnOfpG4EF33+Hu48D9wDnk4Ji6+wPA5tjsqdK1FFgZ8rEHgX4zO6Ke/Si4ZMDMppnZY8BLwD3Ar4At4aQDGALmtyt9Zb4M/AmwN0wfRj7TCVGAvtvMHjazj4V589z9BYDw//C2pS5yNDAM/K2ZPWpmXzezOeQvneU+CPxdeJ2rdLr7c8BfAs8SBZWtwMPk8xz9GXCqmR1mZrOJmpWOJGfHtMxU6ZoPbCxbru7jq+CSAXffE5ocFhBVk99YYbG23ofHzEptsA+Xze6psGhe7hd0iru/jajafqmZndruBFXQC7wNWO7uvw1sJx9NdRWZ2QzgfcC3252WSsxsgKgkvRD4DWAO0fcf1/Zz1N2fJGquuwf4PvA4MF51pXxqOg9QcMlQaBK5D1hMVL0sDahYADzfrnQFpwDvCx3ltxA1NXyZ/KUTAHd/Pvx/iah/4CRgU6nKHv6/1L4UAlEpb8jdHwrTtxMFm7yls+Qs4BF33xSm85bOdwFPu/uwu+8G/h74XfJ7jt7o7m9z91OJmqF+Sf6OaclU6RoiqnGV1H18FVxSZmaDYcQQZjaL6AfyJPBD4P1hsWXAHe1JYcTdP+PuC9z9KKKmkR+4+4fJWToBzGyOmfWVXgNnEDVDrCFKI+Qgre7+IrAxjMaCqD/jCXKWzjL/nv1NYpC/dD4LLDaz2aE/sHQ8c3eOApjZ4eH/64E/IDq2eTumJVOlaw1wgZn1hIFIW0vNZ7XorsgpM7PfIuogm0YUzG9z92vM7Gj2D598FPgP7j7WvpTuZ2anA38chiLnLp0hTavDZC/wLXf/gpkdBtwGvJ4oIzrX3eMdl5kys+OJBkjMAJ4iGjp7EPlL52yitvWj3X1rmJfH4/nnwAeImpgeJRqWPJ+cnaMAZvZ/ifotdwOfcvd783BMzezvgNOB1wKbgKuB71ZKVwjif0M0umwHcJG7/6Se/Si4iIhI4tQsJiIiiVNwERGRxCm4iIhI4hRcREQkcQouIiKSOAUXkRwzs8+FK+dFCkXBRSTfria6RkakUHSdi0gLzGwC+CzRXWQPI7rN+ruILjqbTnQx2pNm9jqiK7QPAQ4GvufufxK2cSPRlc+fMrN5wENhex8F/ojouSV7iS582wtcD/xW2M4PiS7Q22Nm9xHdyPEkoudy3AA8B3yC6F5cn3b3b5el+8+J7m5wGPCn7v6dVA6SdCXVXERat8Xd3w5cQXTbjB+FG1WuBP6stAzw79z9BKLn+pxoZqVnanwceJeZnQ18A/gLd3/M3S8N7/9ueN7KFqLAcr+7nxS2czjRA8hKFgCnAScD1wDHufvvAucBX4qle294733A10q3KxFJgoKLSOtKT3F8BJhw9++F6YeBN4TX04D/bmaPh/nHEQUH3H0nUeb/DeDX7v4/q+zrfcCnwyMcHiF6uNcxZe9/2933hht7vsL+2+Q8DMwPT0YtKT1nxsO2Fjf0qUWq0GOORVr3avi/h+jJo5RNl35jnwIGgJPd/VUz+xpRs1bJm4BfA68zs96y55PE9QBnu/tTNdJS2v+rED32Idw/c6rffA85uFW9dA7VXESy0Q+8EALLfKLnkgBgZguJHm9wGrABuLZsvVHgNWXTa4ArzWxaWPe1Yf1mXBS2sYioFvVQ9cVF6qfgIpKNvwJOMbNHiZ5Dfi/se0DXrcCV7v5Log7895lZ6SFY/wP4gZk9Fh7dcDlRjeRxM/sp0YOomn3y4piZ/RPwD8B/Cs/GEUmERouJdKEwWqzP3be1Oy3SmVRzERGRxKnmIiIiiVPNRUREEqfgIiIiiVNwERGRxCm4iIhI4hRcREQkcQouIiKSuP8PTtLCK987asEAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f667010cbe0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "j = data2[data2['dayofweek'] == 7].plot(kind='scatter', x='maxtemp', y='numtrips')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The data do seem a bit more robust.  If we had even more data, it would be better of course. But in this case, we only have 2014-2016 data for taxi trips, so that's what we will go with."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Machine Learning with Tensorflow\n",
    "\n",
    "We'll use 80% of our dataset for training and 20% of the data for testing the model we have trained. Let's shuffle the rows of the Pandas dataframe so that this division is random.  The predictor (or input) columns will be every column in the database other than the number-of-trips (which is our target, or what we want to predict).\n",
    "\n",
    "The machine learning models that we will use -- linear regression and neural networks -- both require that the input variables are numeric in nature.\n",
    "\n",
    "The day of the week, however, is a categorical variable (i.e. Tuesday is not really greater than Monday). So, we should create separate columns for whether it is a Monday (with values 0 or 1), Tuesday, etc.\n",
    "\n",
    "Against that, we do have limited data (remember: the more columns you use as input features, the more rows you need to have in your training dataset), and it appears that there is a clear linear trend by day of the week. So, we will opt for simplicity here and use the data as-is.  Try uncommenting the code that creates separate columns for the days of the week and re-run the notebook if you are curious about the impact of this simplification."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/envs/py3env/lib/python3.5/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\n",
      "  from ._conv import register_converters as _register_converters\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>dayofweek</th>\n",
       "      <th>mintemp</th>\n",
       "      <th>maxtemp</th>\n",
       "      <th>rain</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>2</td>\n",
       "      <td>32.0</td>\n",
       "      <td>43.0</td>\n",
       "      <td>0.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>279</th>\n",
       "      <td>6</td>\n",
       "      <td>37.9</td>\n",
       "      <td>57.0</td>\n",
       "      <td>0.52</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>163</th>\n",
       "      <td>5</td>\n",
       "      <td>71.1</td>\n",
       "      <td>91.0</td>\n",
       "      <td>0.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>225</th>\n",
       "      <td>6</td>\n",
       "      <td>55.9</td>\n",
       "      <td>78.1</td>\n",
       "      <td>0.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>218</th>\n",
       "      <td>6</td>\n",
       "      <td>55.0</td>\n",
       "      <td>91.9</td>\n",
       "      <td>0.00</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     dayofweek  mintemp  maxtemp  rain\n",
       "9            2     32.0     43.0  0.00\n",
       "279          6     37.9     57.0  0.52\n",
       "163          5     71.1     91.0  0.00\n",
       "225          6     55.9     78.1  0.00\n",
       "218          6     55.0     91.9  0.00"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "shuffled = data2.sample(frac=1, random_state=13)\n",
    "# It would be a good idea, if we had more data, to treat the days as categorical variables\n",
    "# with the small amount of data, we have though, the model tends to overfit\n",
    "#predictors = shuffled.iloc[:,2:5]\n",
    "#for day in range(1,8):\n",
    "#  matching = shuffled['dayofweek'] == day\n",
    "#  key = 'day_' + str(day)\n",
    "#  predictors[key] = pd.Series(matching, index=predictors.index, dtype=float)\n",
    "predictors = shuffled.iloc[:,1:5]\n",
    "predictors[:5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>daynumber</th>\n",
       "      <th>dayofweek</th>\n",
       "      <th>mintemp</th>\n",
       "      <th>maxtemp</th>\n",
       "      <th>rain</th>\n",
       "      <th>numtrips</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>356</td>\n",
       "      <td>2</td>\n",
       "      <td>32.0</td>\n",
       "      <td>43.0</td>\n",
       "      <td>0.00</td>\n",
       "      <td>382112</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>279</th>\n",
       "      <td>86</td>\n",
       "      <td>6</td>\n",
       "      <td>37.9</td>\n",
       "      <td>57.0</td>\n",
       "      <td>0.52</td>\n",
       "      <td>465493</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>163</th>\n",
       "      <td>203</td>\n",
       "      <td>5</td>\n",
       "      <td>71.1</td>\n",
       "      <td>91.0</td>\n",
       "      <td>0.00</td>\n",
       "      <td>363728</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>225</th>\n",
       "      <td>141</td>\n",
       "      <td>6</td>\n",
       "      <td>55.9</td>\n",
       "      <td>78.1</td>\n",
       "      <td>0.00</td>\n",
       "      <td>414711</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>218</th>\n",
       "      <td>148</td>\n",
       "      <td>6</td>\n",
       "      <td>55.0</td>\n",
       "      <td>91.9</td>\n",
       "      <td>0.00</td>\n",
       "      <td>364951</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     daynumber  dayofweek  mintemp  maxtemp  rain  numtrips\n",
       "9          356          2     32.0     43.0  0.00    382112\n",
       "279         86          6     37.9     57.0  0.52    465493\n",
       "163        203          5     71.1     91.0  0.00    363728\n",
       "225        141          6     55.9     78.1  0.00    414711\n",
       "218        148          6     55.0     91.9  0.00    364951"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "shuffled[:5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9      382112\n",
       "279    465493\n",
       "163    363728\n",
       "225    414711\n",
       "218    364951\n",
       "Name: numtrips, dtype: int64"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "targets = shuffled.iloc[:,5]\n",
    "targets[:5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's update our benchmark based on the 80-20 split and the larger dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Just using average=402667.6826484018 has RMSE of 62394.11232075195\n"
     ]
    }
   ],
   "source": [
    "trainsize = int(len(shuffled['numtrips']) * 0.8)\n",
    "avg = np.mean(shuffled['numtrips'][:trainsize])\n",
    "rmse = np.sqrt(np.mean((targets[trainsize:] - avg)**2))\n",
    "print('Just using average={0} has RMSE of {1}'.format(avg, rmse))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Linear regression with tf.contrib.learn\n",
    "\n",
    "We scale the number of taxicab rides by 400,000 so that the model can keep its predicted values in the [0-1] range. The optimization goes a lot faster when the weights are small numbers.  We save the weights into ./trained_model_linear and display the root mean square error on the test dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From <ipython-input-21-3865241c1b45>:9: infer_real_valued_columns_from_input (from tensorflow.contrib.learn.python.learn.estimators.estimator) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please specify feature columns explicitly.\n",
      "WARNING:tensorflow:From /usr/local/envs/py3env/lib/python3.5/site-packages/tensorflow/contrib/learn/python/learn/estimators/estimator.py:142: setup_train_data_feeder (from tensorflow.contrib.learn.python.learn.learn_io.data_feeder) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use tensorflow/transform or tf.data.\n",
      "WARNING:tensorflow:From /usr/local/envs/py3env/lib/python3.5/site-packages/tensorflow/contrib/learn/python/learn/learn_io/data_feeder.py:96: extract_dask_data (from tensorflow.contrib.learn.python.learn.learn_io.dask_io) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please feed input to tf.data to support dask.\n",
      "WARNING:tensorflow:From /usr/local/envs/py3env/lib/python3.5/site-packages/tensorflow/contrib/learn/python/learn/learn_io/data_feeder.py:100: extract_pandas_data (from tensorflow.contrib.learn.python.learn.learn_io.pandas_io) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please access pandas data directly.\n",
      "WARNING:tensorflow:From /usr/local/envs/py3env/lib/python3.5/site-packages/tensorflow/contrib/learn/python/learn/learn_io/data_feeder.py:159: DataFeeder.__init__ (from tensorflow.contrib.learn.python.learn.learn_io.data_feeder) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use tensorflow/transform or tf.data.\n",
      "WARNING:tensorflow:From /usr/local/envs/py3env/lib/python3.5/site-packages/tensorflow/contrib/learn/python/learn/learn_io/data_feeder.py:340: check_array (from tensorflow.contrib.learn.python.learn.learn_io.data_feeder) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please convert numpy dtypes explicitly.\n",
      "WARNING:tensorflow:float64 is not supported by many models, consider casting to float32.\n",
      "WARNING:tensorflow:From /usr/local/envs/py3env/lib/python3.5/site-packages/tensorflow/contrib/learn/python/learn/estimators/estimator.py:182: infer_real_valued_columns_from_input_fn (from tensorflow.contrib.learn.python.learn.estimators.estimator) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please specify feature columns explicitly.\n",
      "WARNING:tensorflow:From /usr/local/envs/py3env/lib/python3.5/site-packages/tensorflow/contrib/learn/python/learn/estimators/linear.py:738: regression_head (from tensorflow.contrib.learn.python.learn.estimators.head) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please switch to tf.contrib.estimator.*_head.\n",
      "WARNING:tensorflow:From /usr/local/envs/py3env/lib/python3.5/site-packages/tensorflow/contrib/learn/python/learn/estimators/estimator.py:1179: BaseEstimator.__init__ (from tensorflow.contrib.learn.python.learn.estimators.estimator) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please replace uses of any Estimator from tf.contrib.learn with an Estimator from tf.estimator.*\n",
      "WARNING:tensorflow:From /usr/local/envs/py3env/lib/python3.5/site-packages/tensorflow/contrib/learn/python/learn/estimators/estimator.py:427: RunConfig.__init__ (from tensorflow.contrib.learn.python.learn.estimators.run_config) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "When switching to tf.estimator.Estimator, use tf.estimator.RunConfig instead.\n",
      "starting to train ... this will take a while ... use verbosity=INFO to get more verbose output\n",
      "WARNING:tensorflow:From /usr/local/envs/py3env/lib/python3.5/site-packages/tensorflow/contrib/learn/python/learn/estimators/head.py:678: ModelFnOps.__new__ (from tensorflow.contrib.learn.python.learn.estimators.model_fn) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "When switching to tf.estimator.Estimator, use tf.estimator.EstimatorSpec. You can use the `estimator_spec` method to create an equivalent one.\n",
      "WARNING:tensorflow:From /usr/local/envs/py3env/lib/python3.5/site-packages/tensorflow/python/util/deprecation.py:497: calling LinearRegressor.predict (from tensorflow.contrib.learn.python.learn.estimators.linear) with outputs=None is deprecated and will be removed after 2017-03-01.\n",
      "Instructions for updating:\n",
      "Please switch to predict_scores, or set `outputs` argument.\n",
      "WARNING:tensorflow:From /usr/local/envs/py3env/lib/python3.5/site-packages/tensorflow/contrib/learn/python/learn/estimators/linear.py:843: calling BaseEstimator.predict (from tensorflow.contrib.learn.python.learn.estimators.estimator) with x is deprecated and will be removed after 2016-12-01.\n",
      "Instructions for updating:\n",
      "Estimator is decoupled from Scikit Learn interface by moving into\n",
      "separate class SKCompat. Arguments x, y and batch_size are only\n",
      "available in the SKCompat class, Estimator will only accept input_fn.\n",
      "Example conversion:\n",
      "  est = Estimator(...) -> est = SKCompat(Estimator(...))\n",
      "WARNING:tensorflow:float64 is not supported by many models, consider casting to float32.\n",
      "LinearRegression has RMSE of 56643.95363906046\n"
     ]
    }
   ],
   "source": [
    "SCALE_NUM_TRIPS = 600000.0\n",
    "trainsize = int(len(shuffled['numtrips']) * 0.8)\n",
    "testsize = len(shuffled['numtrips']) - trainsize\n",
    "npredictors = len(predictors.columns)\n",
    "noutputs = 1\n",
    "tf.logging.set_verbosity(tf.logging.WARN) # change to INFO to get output every 100 steps ...\n",
    "shutil.rmtree('./trained_model_linear', ignore_errors=True) # so that we don't load weights from previous runs\n",
    "estimator = tf.contrib.learn.LinearRegressor(model_dir='./trained_model_linear',\n",
    "                                             feature_columns=tf.contrib.learn.infer_real_valued_columns_from_input(predictors.values))\n",
    "\n",
    "print(\"starting to train ... this will take a while ... use verbosity=INFO to get more verbose output\")\n",
    "def input_fn(features, targets):\n",
    "  return tf.constant(features.values), tf.constant(targets.values.reshape(len(targets), noutputs)/SCALE_NUM_TRIPS)\n",
    "estimator.fit(input_fn=lambda: input_fn(predictors[:trainsize], targets[:trainsize]), steps=10000)\n",
    "\n",
    "pred = np.multiply(list(estimator.predict(predictors[trainsize:].values)), SCALE_NUM_TRIPS )\n",
    "rmse = np.sqrt(np.mean(np.power((targets[trainsize:].values - pred), 2)))\n",
    "print('LinearRegression has RMSE of {0}'.format(rmse))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The RMSE here (57K) is lower than the benchmark (62K) indicates that we are doing about 10% better with the machine learning model than we would be if we were to just use the historical average (our benchmark)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Neural network with tf.contrib.learn\n",
    "\n",
    "Let's make a more complex model with a few hidden nodes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:float64 is not supported by many models, consider casting to float32.\n",
      "starting to train ... this will take a while ... use verbosity=INFO to get more verbose output\n",
      "WARNING:tensorflow:From /usr/local/envs/py3env/lib/python3.5/site-packages/tensorflow/python/util/deprecation.py:497: calling DNNRegressor.predict (from tensorflow.contrib.learn.python.learn.estimators.dnn) with outputs=None is deprecated and will be removed after 2017-03-01.\n",
      "Instructions for updating:\n",
      "Please switch to predict_scores, or set `outputs` argument.\n",
      "WARNING:tensorflow:float64 is not supported by many models, consider casting to float32.\n"
     ]
    }
   ],
   "source": [
    "SCALE_NUM_TRIPS = 600000.0\n",
    "trainsize = int(len(shuffled['numtrips']) * 0.8)\n",
    "testsize = len(shuffled['numtrips']) - trainsize\n",
    "npredictors = len(predictors.columns)\n",
    "noutputs = 1\n",
    "tf.logging.set_verbosity(tf.logging.WARN) # change to INFO to get output every 100 steps ...\n",
    "shutil.rmtree('./trained_model', ignore_errors=True) # so that we don't load weights from previous runs\n",
    "estimator = tf.contrib.learn.DNNRegressor(model_dir='./trained_model',\n",
    "                                          hidden_units=[5, 5],                             \n",
    "                                          feature_columns=tf.contrib.learn.infer_real_valued_columns_from_input(predictors.values))\n",
    "\n",
    "print(\"starting to train ... this will take a while ... use verbosity=INFO to get more verbose output\")\n",
    "def input_fn(features, targets):\n",
    "  return tf.constant(features.values), tf.constant(targets.values.reshape(len(targets), noutputs)/SCALE_NUM_TRIPS)\n",
    "estimator.fit(input_fn=lambda: input_fn(predictors[:trainsize], targets[:trainsize]), steps=10000)\n",
    "\n",
    "pred = np.multiply(list(estimator.predict(predictors[trainsize:].values)), SCALE_NUM_TRIPS )\n",
    "rmse = np.sqrt(np.mean((targets[trainsize:].values - pred)**2))\n",
    "print('Neural Network Regression has RMSE of {0}'.format(rmse))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Using a neural network results in similar performance to the linear model when I ran it -- it might be because there isn't enough data for the NN to do much better. (NN training is a non-convex optimization, and you will get different results each time you run the above code)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Running a trained model\n",
    "\n",
    "So, we have trained a model, and saved it to a file. Let's use this model to predict taxicab demand given the expected weather for three days.\n",
    "\n",
    "Here we make a Dataframe out of those inputs, load up the saved model (note that we have to know the model equation -- it's not saved in the model file) and use it to predict the taxicab demand."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:float64 is not supported by many models, consider casting to float32.\n",
      "WARNING:tensorflow:float64 is not supported by many models, consider casting to float32.\n",
      "[354762.78 306764.7  387226.62]\n"
     ]
    }
   ],
   "source": [
    "input = pd.DataFrame.from_dict(data = \n",
    "                               {'dayofweek' : [4, 5, 6],\n",
    "                                'mintemp' : [60, 40, 50],\n",
    "                                'maxtemp' : [70, 90, 60],\n",
    "                                'rain' : [0, 0.5, 0]})\n",
    "# read trained model from ./trained_model\n",
    "estimator = tf.contrib.learn.LinearRegressor(model_dir='./trained_model_linear',\n",
    "                                          feature_columns=tf.contrib.learn.infer_real_valued_columns_from_input(input.values))\n",
    "\n",
    "pred = np.multiply(list(estimator.predict(input.values)), SCALE_NUM_TRIPS )\n",
    "print(pred)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Looks like we should tell some of our taxi drivers to take the day off on Thursday (day=5). No wonder -- the forecast calls for extreme weather fluctuations on Thursday."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Copyright 2017 Google Inc. Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
